package com.xbongbong.parent.abstracts;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasAppEntity;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasMenuEntity;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessTemplateEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasFormDataEsModel;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.enums.SheetTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.LinkDetailPojo;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.model.CloudCodeControlModel;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.PaasMenuModel;
import com.xbongbong.paas.model.PaasProcessTemplateModel;
import com.xbongbong.paas.pojo.ButtonExtraPojo;
import com.xbongbong.paas.pojo.ButtonPojo;
import com.xbongbong.paas.pojo.ShareConditionFormatPojo;
import com.xbongbong.paas.pojo.dto.ColumnSetListDTO;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.vo.PaasFormDataEsListVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.parent.interfaces.BusinessListService;
import com.xbongbong.parent.parse.data.FormDataListAnalysisDataHelp;
import com.xbongbong.parent.pojo.list.ConditionListPojo;
import com.xbongbong.parent.pojo.list.ConditionListResultPoJo;
import com.xbongbong.parent.pojo.list.DataAnalysisListPojo;
import com.xbongbong.parent.pojo.list.FieldListPojo;
import com.xbongbong.parent.pojo.list.PermissionListPojo;
import com.xbongbong.pro.applist.pojo.AppListPojo;
import com.xbongbong.pro.applist.pojo.vo.ListAppVO;
import com.xbongbong.pro.constant.RangeScreenConstant;
import com.xbongbong.pro.domain.entity.CloudCodeControlEntity;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.cloudcode.enums.CloudCodeControlEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formexplain.pojo.HandleExplainPojo;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ErrorMessageConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ext.WorkOrderFormEntityExt;
import com.xbongbong.saas.enums.ListBatchEnum;
import com.xbongbong.saas.enums.ListBottomButtonEnum;
import com.xbongbong.saas.enums.ListGroupEnum;
import com.xbongbong.saas.enums.ListTopButtonEnum;
import com.xbongbong.saas.enums.SaasBatchEnum;
import com.xbongbong.saas.enums.SaasButtonEnum;
import com.xbongbong.saas.enums.SaasSubButtonEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.model.WorkOrderFormModel;
import com.xbongbong.saas.service.toolbox.help.SaasListDataPermissionHelp;
import com.xbongbong.sys.help.ProPermissionHelp;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.util.ContractCompareUtil;
import com.xbongbong.util.SaasLinkProductUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * 各个业务列表的父类，用于公共方法的封装，若各个业务有各自的需求，请在各自子类重写此方法
 * @author 吴峰
 * @date 2021/12/20 14:00
 */
@Component
public abstract class AbstractBusinessListService implements BusinessListService {

    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractBusinessListService.class);

    @Resource
    private PaasMenuModel paasMenuModel;

    @Resource
    private PaasFormDataEsModel paasFormDataEsModel;
    @Resource
    private FormDataListAnalysisDataHelp formDataListAnalysisDataHelp;
    @Resource
    private CloudCodeControlModel cloudCodeControlModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private IndexTypeModel indexTypeModel;
    @Resource
    private WorkOrderFormModel workOrderFormModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private UserModel userModel;
    @Resource
    private PaasProcessTemplateModel paasProcessTemplateModel;
    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private ContractCompareUtil contractCompareUtil;
    @Resource
    private SaasListDataPermissionHelp saasListDataPermissionHelp;

    @Override
    public PaasFormDataEsListVO list(FormDataListDTO formDataListDTO) throws XbbException {
        boolean notExport = Objects.isNull(formDataListDTO.getFromExport()) || Objects.equals(0, formDataListDTO.getFromExport());
        if ( !notExport ) {
            // 导入调用，导入不需要走下面解析方法
            return getDataList(formDataListDTO);
        }
        if (Objects.equals(PlatFormEnum.WEB.getValue(), formDataListDTO.getPlatform())) {
            return webList(formDataListDTO);
        } else if (Objects.equals(PlatFormEnum.DINGTALK.getValue(), formDataListDTO.getPlatform())) {
            // 手机端方法，但是只有字段解析以及摘要等信息，给图表穿透使用，手机端列表调用非此方法
            return dingtalkListNoOperator(formDataListDTO);
        }
        // api不会传platform调用此方法，在此处做些兼容
        return getDataList(formDataListDTO);
    }

    private PaasFormDataEsListVO getDataList(FormDataListDTO formDataListDTO) throws XbbException {
        PermissionListPojo permissionListPojo = new PermissionListPojo(formDataListDTO.getFormId(), formDataListDTO.getMenuId(), formDataListDTO.getSaasMark(), formDataListDTO.getBusinessType(), formDataListDTO.getDistributorMark(), formDataListDTO.getSubBusinessType(), formDataListDTO.getLoginUser());
        // 1. 获取权限
        List<ConditionsEntityExt> permissionConditionList = getPermission(permissionListPojo);
        // 处理共享权限的逻辑，把权限的条件一起放到共享权限中处理
        ShareConditionFormatPojo sharePermission = saasListDataPermissionHelp.getSharePermission(permissionConditionList, Collections.singletonList(formDataListDTO.getFormId()), formDataListDTO.getLoginUser());

        ConditionListPojo conditionListPojo = new ConditionListPojo(formDataListDTO.getCorpid(), formDataListDTO.getFormId(), formDataListDTO.getBusinessType(), formDataListDTO.getListGroupId(), formDataListDTO.getDefaultGroup(), formDataListDTO.getConditions(), formDataListDTO.getShouldConditions(), formDataListDTO.getLoginUser(), formDataListDTO.getPlatform(), formDataListDTO.getSubBusinessType(), formDataListDTO.getStatusFilter(), formDataListDTO.getCommonFilter(), formDataListDTO.getStatisticsType());
        // 2. 获取条件
        ConditionListResultPoJo conditionListResultPoJo;
        if (Objects.equals(formDataListDTO.getPlatform(), PlatFormEnum.WEB.getValue())) {
            conditionListResultPoJo = getCondition(conditionListPojo);
        } else {
            conditionListResultPoJo = mobileGetCondition(conditionListPojo);
        }
        //
        formDataListDTO.setConditions(conditionListResultPoJo.getConditionList());
        formDataListDTO.setShouldConditions(conditionListResultPoJo.getShouldConditionList());
        // 共享权限es拼接处理
        formDataListDTO.setSharePermission(sharePermission);
        // 获取表单
        PaasFormEntityExt paasFormEntityExt = getForm(formDataListDTO);
        FieldListPojo fieldListPojo = new FieldListPojo(formDataListDTO.getCorpid(), paasFormEntityExt.getId(), formDataListDTO.getAppId(), formDataListDTO.getDefaultGroup(), formDataListDTO.getListGroupId(), formDataListDTO.getSaasMark(), formDataListDTO.getBusinessType(), formDataListDTO.getSubBusinessType(), formDataListDTO.getLoginUser(), paasFormEntityExt);
        // 3. 获取解释
        HandleExplainPojo handleExplainPojo = getExplain(fieldListPojo);

        // 团队权限相关的拼接放到共享权限中处理
//        formDataListDTO.getConditions().addAll(permissionConditionList);
        Map<String, FieldAttrEntity> explainMap = new HashMap<>(handleExplainPojo.getExplainList().size());
        Map<String, FieldAttrEntity> finalExplainMap = explainMap;
        handleExplainPojo.getExplainList().forEach(item-> finalExplainMap.put(item.getAttr(), item));
        formDataListDTO.setExplainMap(explainMap);

        // 开启电话掩码后不允许进行电话字段的查询
        List<ConditionsEntityExt> conditions = formDataListDTO.getConditions();
        if (CollectionsUtil.isNotEmpty(conditions)) {
            for (ConditionsEntityExt condition : conditions) {
                FieldAttrEntity fieldAttr = explainMap.get(condition.getAttr());
                if (Objects.nonNull(fieldAttr) && ExplainUtil.isOpenTelephoneMask(fieldAttr, formDataListDTO.getLoginUser())) {
                    throw new XbbException(ErrorCodeEnum.API_ERROR_352000);
                }
            }
        }

        //字段排序条件封装
        setSortMap(formDataListDTO);
        // 4. 获取数据
        IndexTypeEnum indexTypeEnum = indexTypeModel.getIndexType(formDataListDTO.getCorpid(), formDataListDTO.getBusinessType(), formDataListDTO.getSaasMark());
        PaasFormDataEsListVO formDataEsListVO = paasFormDataEsModel.list(formDataListDTO, indexTypeEnum);
        List<FieldAttrEntity> headList = handleExplainByDataList(handleExplainPojo.getExplainList(), paasFormEntityExt, formDataEsListVO);
        formDataEsListVO.setHeadList(headList);
        formDataEsListVO.setForm(paasFormEntityExt);
        explainMap = new HashMap<>(headList.size());
        for (FieldAttrEntity item : headList) {
            explainMap.put(item.getAttr(), item);
        }
        formDataEsListVO.setExplainMap(explainMap);
        formDataEsListVO.setTotal(formDataEsListVO.getPageHelper().getRowsCount());
        return formDataEsListVO;
    }



    /**
     * 根据数据封装下字段解释
     * @param headList
     * @param paasFormEntityExt
     * @param formDataListVO
     * @return
     */
    protected List<FieldAttrEntity> handleExplainByDataList(List<FieldAttrEntity> headList,  PaasFormEntityExt paasFormEntityExt, PaasFormDataEsListVO formDataListVO) throws XbbException{
        return headList;
    }

    @Override
    public ListAppVO dingtalkList(FormDataListDTO formDataListDTO) throws XbbException {
        // 获取数据
        ListAppVO listAppVO = new ListAppVO();
        PaasFormDataEsListVO paasFormDataEsListVO = dingtalkListNoOperator(formDataListDTO);
        PaasFormEntityExt paasFormEntityExt = paasFormDataEsListVO.getForm();

        // 字段解析方法-手机端解析方法
        DataAnalysisListPojo dataAnalysisListPojo = new DataAnalysisListPojo(formDataListDTO.getCorpid(), formDataListDTO.getUserId(), formDataListDTO.getLoginUser(), formDataListDTO.getFormId(), formDataListDTO.getDistributorMark(), formDataListDTO.getSaasMark(), formDataListDTO.getBusinessType(), formDataListDTO.getSubBusinessType(), formDataListDTO.getPage(), formDataListDTO.getPageSize(), paasFormDataEsListVO.getHeadList(), paasFormEntityExt, paasFormDataEsListVO.getPaasFormDataESList(),formDataListDTO.getAnalysisAmountOfThousandBitsWithOriginalValue());
        dataAnalysisListPojo.setFormDataList(paasFormDataEsListVO.getPaasFormDataESList());
        // 手机端操作（包括关注，提醒等信息）
        List<AppListPojo> list = dingtalkOperate(dataAnalysisListPojo);
        // 新建权限
        listAppVO.setTotalCount(paasFormDataEsListVO.getTotal());
        listAppVO.setAddPermission(isHaveAddPermission(formDataListDTO));
        // 底部按钮
        List<ButtonPojo> bottomButtonList = bottomButton(formDataListDTO, paasFormDataEsListVO.getHeadList());
        listAppVO.setBottomPermissions(bottomButtonList);
        listAppVO.setPageHelper(paasFormDataEsListVO.getPageHelper());
        listAppVO.setList(list);
        return listAppVO;
    }

    /**
     * 手机端列表数据获取以及解析成摘要，标题，标签
     * @param formDataListDTO
     * @return
     * @throws XbbException
     */
    public PaasFormDataEsListVO dingtalkListNoOperator(FormDataListDTO formDataListDTO) throws XbbException {
        // 获取数据
        PaasFormDataEsListVO paasFormDataEsListVO = getDataList(formDataListDTO);
        PaasFormEntityExt paasFormEntityExt = paasFormDataEsListVO.getForm();
        // 拼装实体
        DataAnalysisListPojo dataAnalysisListPojo = new DataAnalysisListPojo(formDataListDTO.getCorpid(), formDataListDTO.getUserId(), formDataListDTO.getLoginUser(), formDataListDTO.getFormId(), formDataListDTO.getDistributorMark(), formDataListDTO.getSaasMark(), formDataListDTO.getBusinessType(), formDataListDTO.getSubBusinessType(), formDataListDTO.getPage(), formDataListDTO.getPageSize(), paasFormDataEsListVO.getHeadList(), paasFormEntityExt, paasFormDataEsListVO.getPaasFormDataESList(),formDataListDTO.getAnalysisAmountOfThousandBitsWithOriginalValue());
        // 字段解析方法-手机端解析方法
        List<PaasFormDataEntityExt> formDataList = dingtalkDataAnalysis(dataAnalysisListPojo);
        paasFormDataEsListVO.setPaasFormDataESList(formDataList);
        return paasFormDataEsListVO;
    }

    @Override
    public PaasFormDataEsListVO webList(FormDataListDTO formDataListDTO) throws XbbException {
        // 获取数据
        PaasFormDataEsListVO paasFormDataEsListVO = getDataList(formDataListDTO);
        PaasFormEntityExt paasFormEntityExt = paasFormDataEsListVO.getForm();

        DataAnalysisListPojo dataAnalysisListPojo = new DataAnalysisListPojo(formDataListDTO.getCorpid(), formDataListDTO.getUserId(), formDataListDTO.getLoginUser(), formDataListDTO.getFormId(), formDataListDTO.getDistributorMark(), formDataListDTO.getSaasMark(), formDataListDTO.getBusinessType(), formDataListDTO.getSubBusinessType(), formDataListDTO.getPage(), formDataListDTO.getPageSize(),
                paasFormDataEsListVO.getHeadList(), paasFormDataEsListVO.getForm(), paasFormDataEsListVO.getPaasFormDataESList(), formDataListDTO.getAnalysisAmountOfThousandBitsWithOriginalValue());

        //审批分组的数据没有操作按钮
        if (!Objects.equals(1, formDataListDTO.getDefaultGroup()) || !Objects.equals(formDataListDTO.getListGroupId(), Long.valueOf(ListGroupEnum.APPROVAL.getCode()))) {
            // 5. 列表的操作按钮-web端独有
            webOperate(dataAnalysisListPojo);
        }

        // 6. 字段解析方法-web端解析方法
        List<PaasFormDataEntityExt> formDataList = webDataAnalysis(dataAnalysisListPojo);
        paasFormDataEsListVO.setPaasFormDataESList(formDataList);
        paasFormDataEsListVO.setForm(paasFormEntityExt);
        formDataListDTO.setMenuId(paasFormEntityExt.getMenuId());
        // 底部按钮-web端独有
        List<ButtonPojo> bottomButtonList = bottomButton(formDataListDTO, paasFormDataEsListVO.getHeadList());
        // 顶部按钮-web端独有
        List<ButtonPojo> topButtonList = topButton(formDataListDTO);
        paasFormDataEsListVO.setTopPermissions(topButtonList);
        paasFormDataEsListVO.setBottomPermissions(bottomButtonList);
        ColumnSetListDTO columnSetListDTO = new ColumnSetListDTO(formDataListDTO.getCorpid(), formDataListDTO.getAppId(), formDataListDTO.getFormId(), formDataListDTO.getBusinessType(), formDataListDTO.getSubBusinessType(), formDataListDTO.getListGroupId(), formDataListDTO.getUserId());
        //关联产品关联显示字段列表页解析，放在这里是因为移动端不需要，暂时 todo
        SaasLinkProductUtil.productLinkShowField(paasFormDataEsListVO.getHeadList());
        // 字段重排序
        explainFieldSort(columnSetListDTO, paasFormDataEsListVO.getHeadList());
        // 处理表单冻结列，隐藏列
        setFixedAndInvisible(columnSetListDTO, paasFormDataEsListVO.getHeadList());
        paasFormDataEsListVO.setExplainMap(new HashMap<>(BasicConstant.ZERO));
        return paasFormDataEsListVO;
    }


    @Override
    public List<ConditionsEntityExt> webCommonFilter(ConditionListPojo conditionListPojo) throws XbbException {
        List<ConditionsEntityExt> conditionsEntityExtList = conditionListPojo.getConditionList();
        conditionsEntityExtList = conditionsEntityExtList == null ? new ArrayList<>() : conditionsEntityExtList;
        JSONObject commonFilter = conditionListPojo.getCommonFilter();
        if (Objects.isNull(commonFilter)) {
            return conditionsEntityExtList;
        }
        JSONObject rangeScreen = commonFilter.getJSONObject(RangeScreenConstant.RANGE_SCREEN);
        if (Objects.isNull(rangeScreen) || Objects.isNull(rangeScreen.get(RangeScreenConstant.TYPE)) || StringUtil.isEmpty(rangeScreen.getString(RangeScreenConstant.TYPE)) || Objects.isNull(rangeScreen.get(RangeScreenConstant.VALUE))) {
            return conditionsEntityExtList;
        }

        String type;
        List<String> values;
        String attr;
        try {
            type = rangeScreen.getString(RangeScreenConstant.TYPE);
            values = rangeScreen.getJSONArray(RangeScreenConstant.VALUE).toJavaList(String.class);
            attr = rangeScreen.getString(RangeScreenConstant.ATTR);
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), "AbstractBusinessList.commonFilter中的commonFilter参数错误");
        }

        if (CollectionsUtil.isEmpty(values)) {
            return conditionsEntityExtList;
        }
        // 竞争对手不需要可见范围筛选不需要筛选子部门
        if (Objects.equals(type, RangeScreenConstant.DEPARTMENT) && !Objects.equals(conditionListPojo.getBusinessType(), XbbRefTypeEnum.COMPETITOR.getCode())) {
            List<Long> deptIds = new ArrayList<>(values.size());
            values.forEach(item -> deptIds.add(Long.valueOf(item)));
            values = userModel.getUserIdsRecursionDep(deptIds, conditionListPojo.getCorpid(), 1, true);
        }
        if (CollectionsUtil.isEmpty(values)) {
            // 预防部门下没有员工，给个userId为"0"的，防止条件失效
            values = Arrays.asList("0");
        }
        // 范围筛选
        Integer fieldType = getFieldTypeByAttr(attr);

        ConditionsEntityExt conditionsEntityExt = new ConditionsEntityExt(attr, "", fieldType, ConditionEnum.IN.getSymbol(), new ArrayList<>(values));
        conditionsEntityExtList.add(conditionsEntityExt);
        return conditionsEntityExtList;
    }

    /**
     * 该方法用于列表页的范围筛选
     * 业务层，由各个子类实现，如：
     * 1、报价单用范围筛选可选择负责人、协同人，报价人，其中负责人和协同人在调用该方法层已实现，此处无需实现，除非有特殊逻辑
     * 2、合同订单范围筛选可选择负责人、协同人，签订人，其中负责人和协同人在调用该方法层已实现，此处无需实现，除非有特殊逻辑
     * @param attr
     * @return
     */
    protected Integer getFieldTypeByAttr(String attr) {
        Integer fieldType = 0;
        if (Objects.equals(attr, FieldTypeEnum.OWNERID.getAlias())) {
            fieldType = FieldTypeEnum.OWNERID.getType();
        }  else if (Objects.equals(attr, FieldTypeEnum.COUSERID.getAlias())) {
            fieldType = FieldTypeEnum.COUSERID.getType();
        } else if (Objects.equals(attr, FieldTypeEnum.PRE_OWNER_ID.getAlias())) {
            fieldType = FieldTypeEnum.PRE_OWNER_ID.getType();
        }
        return fieldType;
    }

    /**
     * 底部按钮权限获取，此处为公共方法，如果需要实现业务层独有逻辑，请在各自逻辑下实现
     * @param formDataListDTO
     * @return
     * @throws XbbException
     */
    @Override
    public List<ButtonPojo> topButton(FormDataListDTO formDataListDTO) throws XbbException {
        try {
            List<ButtonPojo> topButtonList = new ArrayList<>();
            UserVO userVO = formDataListDTO.getLoginUser();
            Long menuId = formDataListDTO.getMenuId();
            String corpid = formDataListDTO.getCorpid();
            Integer subBusinessType = formDataListDTO.getSubBusinessType();
            Set<String> permSet = userVO.getPermSet();
            PaasMenuEntity paasMenuEntity = paasMenuModel.getByKey(menuId, corpid);
            if (Objects.isNull(paasMenuEntity)) {
                return topButtonList;
            }
            List<ListTopButtonEnum> topButtonEnumList = ListTopButtonEnum.getByBusinessType(subBusinessType);
            Integer distributorMark = paasMenuEntity.getDistributorMark();
            for (ListTopButtonEnum topButtonEnum : topButtonEnumList) {
                String permission = topButtonEnum.getProPermissionAlias();
                // permission为1的按钮一直存在的或还没加权限alias
                if (!permSet.contains(permission) && !Objects.equals(permission, StringConstant.POSITIVE_NUMBER)) {
                    continue;
                }
                ButtonPojo buttonPojo = new ButtonPojo();
                BeanUtil.copyProperties(topButtonEnum.getAnEnum(), buttonPojo);
                if (Objects.equals(formDataListDTO.getListGroupId(), Long.valueOf(ListGroupEnum.APPROVAL.getCode()))
                    && (Objects.equals(topButtonEnum.getAnEnum().getAttr(), SaasButtonEnum.IMPORT.getAttr()))) {
                    continue;
                }
                if (Objects.equals(topButtonEnum.getAnEnum().getAttr(), SaasButtonEnum.IMPORT.getAttr())) {
                    ButtonExtraPojo buttonExtraPojo = new ButtonExtraPojo();
                    buttonExtraPojo.setImportTitle(paasMenuEntity.getName());
                    buttonPojo.setButtonExtra(buttonExtraPojo);
                }
                if (Objects.equals(topButtonEnum.getAnEnum().getAttr(), SaasButtonEnum.EXPORT.getAttr())) {
                    List<ButtonPojo> subButtonList = new ArrayList<ButtonPojo>(){{
                        add(new ButtonPojo(){{BeanUtil.copyProperties(topButtonEnum.getAnEnum(), this);}});
                    }};
                    List<SaasSubButtonEnum> saasSubButtonEnumList = SaasSubButtonEnum.getByPermissionAlias(XbbRefTypeEnum.transferBusinessType4Distributor(formDataListDTO.getSubBusinessType(),formDataListDTO.getDistributorMark()),topButtonEnum,formDataListDTO.getLoginUser().getPermSet());
                    saasSubButtonEnumList.forEach(item->{
                        subButtonList.add(new ButtonPojo(){{setAttr(item.getAlias());setValue(item.getName());}});
                    });
                    buttonPojo.setSubButtons(subButtonList);
                }

                buttonPojo.setDistributorMark(distributorMark);
                topButtonList.add(buttonPojo);
            }
            return topButtonList;
        }catch (Exception e) {
            LOGGER.error("AbstractBusinessListService.topButton error", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    /**
     * 底部按钮权限获取，此处为公共方法，如果需要实现业务层独有逻辑，请在各自逻辑下实现
     * @param formDataListDTO
     * @param explainList
     * @return
     * @throws XbbException
     */
    @Override
    public List<ButtonPojo> bottomButton(FormDataListDTO formDataListDTO, List<FieldAttrEntity> explainList) throws XbbException {
        try {
            List<ButtonPojo> batchButtonList = new ArrayList<>();
            UserVO userVO = formDataListDTO.getLoginUser();
            String corpid = formDataListDTO.getCorpid();
            Long menuId = formDataListDTO.getMenuId();
            Integer businessType = formDataListDTO.getBusinessType();
            Integer subBusinessType = formDataListDTO.getSubBusinessType();
            Set<String> permSet = userVO.getPermSet();
            PaasMenuEntity paasMenuEntity = paasMenuModel.getByKey(menuId, corpid);
            if (Objects.isNull(paasMenuEntity)) {
                return batchButtonList;
            }
            Integer distributorMark = paasMenuEntity.getDistributorMark();
            List<ListBottomButtonEnum> bottomButtonEnumList = ListBottomButtonEnum.getByBusinessType(subBusinessType);
            //该公司是否开启客户公海高级模式
            boolean isCustomerSeniorMode = commonHelp.isCustomerPublicPoolSeniorModel(corpid);
            //该公司是否开启线索公海高级模式
            boolean isClueSeniorMode = commonHelp.isCluePublicPoolSeniorModel(corpid);
            for (ListBottomButtonEnum bottomButtonEnum : bottomButtonEnumList) {
                String permission = bottomButtonEnum.getProPermissionAlias();
                // permission为1的按钮一直存在的或还没加权限alias
                if (!permSet.contains(permission) && !Objects.equals(permission, StringConstant.POSITIVE_NUMBER)) {
                    continue;
                }
                ButtonPojo buttonPojo = new ButtonPojo();
                BeanUtil.copyProperties(bottomButtonEnum.getAnEnum(), buttonPojo);
                if (Objects.equals(bottomButtonEnum.getAnEnum().getAttr(), SaasButtonEnum.IMPORT.getAttr())) {
                    ButtonExtraPojo buttonExtraPojo = new ButtonExtraPojo();
                    buttonExtraPojo.setImportTitle(paasMenuEntity.getName());
                    buttonPojo.setButtonExtra(buttonExtraPojo);
                }
                buttonPojo.setDistributorMark(distributorMark);
                //塞入底部
                batchButtonList.add(buttonPojo);
            }
            List<ListBatchEnum> listBatchEnumList = ListBatchEnum.getByBusinessType(subBusinessType);
            // 目前整理的审批中列表支持的批量操作只有打印，具体信息见语雀文档：https://xbb.yuque.com/kgwhab/lrgi3l/zd25ra
            if (Objects.equals(formDataListDTO.getDefaultGroup(), 1) && Objects.equals(formDataListDTO.getListGroupId(), Long.valueOf(ListGroupEnum.APPROVAL.getCode()))) {
                listBatchEnumList.removeIf(item -> !Objects.equals(item.getAnEnum(), SaasBatchEnum.BATCH_PRINT));
            }
            Map<String, Boolean> teamMap = getTeamListPermissionMap(formDataListDTO, explainList);
            List<String> listTeamBatchButtonAttr = SaasBatchEnum.getListTeamBatchButton();
            for (ListBatchEnum batchEnum : listBatchEnumList) {
                if (!Objects.equals(DistributorMarkEnum.DISTRIBUTOR.getCode(), distributorMark) && listTeamBatchButtonAttr.contains(batchEnum.getAnEnum().getAttr())) {
                    Boolean teamBatchPer = teamMap.get(batchEnum.getAnEnum().getAttr());
                    if (Objects.nonNull(teamBatchPer) && !teamBatchPer) {
                        continue;
                    }
                }
                // permission为1的按钮一直存在的
                String permissionAlias = batchEnum.getProPermissionAlias();
                if (!permSet.contains(permissionAlias) && !Objects.equals(permissionAlias, StringConstant.POSITIVE_NUMBER) && !Objects.equals(batchEnum.getAnEnum().getAttr(), SaasBatchEnum.CONTRACT_COMPARE.getAttr())) {
                    continue;
                }
                //只有公司开了客户或者线索公海高级模式,才会返回变更分组权限
                if (Objects.equals(businessType,XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())){
                    if (Objects.equals(batchEnum.getAnEnum().getAttr(),SaasBatchEnum.SWITCH_PUBLIC_GROUP.getAttr()) && !isCustomerSeniorMode){
                        continue;
                    }
                }
                if (Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode())){
                    if (Objects.equals(batchEnum.getAnEnum().getAttr(),SaasBatchEnum.SWITCH_PUBLIC_GROUP.getAttr()) && !isClueSeniorMode){
                        continue;
                    }
                }
                ButtonPojo buttonPojo = new ButtonPojo();
                BeanUtil.copyProperties(batchEnum.getAnEnum(), buttonPojo);
                if (Objects.equals(batchEnum.getAnEnum().getAttr(), SaasBatchEnum.MERGE_INVOICE.getAttr())) {
                    buttonPojo.addBusinessType(XbbRefTypeEnum.INVOICE.getCode());
                }
                if (Objects.equals(batchEnum.getAnEnum().getAttr(), SaasBatchEnum.ADD_VISIT_PLAN.getAttr())) {
                    buttonPojo.addBusinessType(XbbRefTypeEnum.COMMUNICATE_PLAN.getCode());
                }
                if (Objects.equals(batchEnum.getAnEnum().getAttr(), SaasBatchEnum.COMMUNICATE_NOTIFY.getAttr())) {
                    buttonPojo.addBusinessType(XbbRefTypeEnum.PUSH_NOTIFY.getCode());
                }
                if (Objects.equals(batchEnum.getAnEnum().getAttr(), SaasBatchEnum.PURCHASE.getAttr())) {
                    buttonPojo.addBusinessType(XbbRefTypeEnum.PURCHASE.getCode());
                }
                if (Objects.equals(batchEnum.getAnEnum().getAttr(), SaasBatchEnum.MERGE_PAYMENT.getAttr()) ){
                    buttonPojo.addBusinessType(XbbRefTypeEnum.PAYMENT_SHEET.getCode());
                }
                if (Objects.equals(batchEnum.getAnEnum().getAttr(), SaasBatchEnum.MEEGE_PURCHASE_INVOICE.getAttr()) ){
                    buttonPojo.addBusinessType(XbbRefTypeEnum.PURCHASE_INVOICE.getCode());
                }
                if (Objects.equals(batchEnum.getAnEnum().getAttr(), SaasBatchEnum.SET_PAID.getAttr())) {
                    if (commonHelp.isOpenWorkFlow(corpid)) {
                        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        params.put("del", 0);
                        params.put("businessType", XbbRefTypeEnum.PAYMENT_SHEET.getCode());
                        params.put("corpid", corpid);
                        params.put("distributorMark", distributorMark);
                        //查询回款单的paasForm信息
                        List<PaasFormEntityExt> paasFormEntityExts = paasFormModel.findEntitys(params);
                        if (CollectionsUtil.isNotEmpty(paasFormEntityExts) && Objects.equals(paasFormEntityExts.get(0).getIsProcessForm(), 1)) {
                            buttonPojo.setDisabled(1);
                            buttonPojo.setNeedRemind(1);
                            buttonPojo.setRemindMsg(I18nMessageUtil.getMessage(ErrorMessageConstant.PAYMENT_SHEET_APPROVEL_NOT_ADD));
                        }
                    } else {
                        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        params.put("del", 0);
                        params.put("businessType", XbbRefTypeEnum.PAYMENT_SHEET.getCode());
                        params.put("corpid", corpid);
                        params.put("distributorMark", distributorMark);
                        //查询回款单的paasForm信息
                        List<PaasFormEntityExt> paasFormEntityExts = paasFormModel.findEntitys(params);
                        if (CollectionsUtil.isNotEmpty(paasFormEntityExts)) {
                            params.put("formId", paasFormEntityExts.get(BasicConstant.ZERO).getId());
                        }
                        params.put("enable",1);
                        params.put(ParameterConstant.COLUMNS, "enable");
                        List<PaasProcessTemplateEntityExt>  processList = paasProcessTemplateModel.list(params);
                        if (!processList.isEmpty() && Objects.equals(processList.get(0).getEnable(), 1)) {
                            buttonPojo.setDisabled(1);
                            buttonPojo.setNeedRemind(1);
                            buttonPojo.setRemindMsg(I18nMessageUtil.getMessage(ErrorMessageConstant.PAYMENT_SHEET_APPROVEL_NOT_ADD));
                        }
                    }

                }
                if (Objects.equals(batchEnum.getAnEnum().getAttr(), SaasBatchEnum.MERGE_PAY_PAID.getAttr()) ){
                    buttonPojo.addBusinessType(XbbRefTypeEnum.PAY_SHEET.getCode());
                }
                if (Objects.equals(batchEnum.getAnEnum().getAttr(), SaasBatchEnum.SET_PAY_PAID.getAttr())) {
                    if (commonHelp.isOpenWorkFlow(corpid)) {
                        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        params.put("del", 0);
                        params.put("businessType", XbbRefTypeEnum.PAY_SHEET.getCode());
                        params.put("corpid", corpid);
                        List<PaasFormEntity> paasFormEntities = paasFormModel.findEntity(params);
                        if (CollectionsUtil.isNotEmpty(paasFormEntities) && Objects.equals(paasFormEntities.get(0).getIsProcessForm(), 1)) {
                            buttonPojo.setDisabled(1);
                            buttonPojo.setNeedRemind(1);
                            buttonPojo.setRemindMsg(I18nMessageUtil.getMessage(ErrorMessageConstant.PAY_SHEET_APPROVEL_NOT_ADD));
                        }
                    } else {
                        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        params.put("del", 0);
                        params.put("businessType", XbbRefTypeEnum.PAY_SHEET.getCode());
                        params.put("corpid", corpid);
                        params.put("enable",1);
                        params.put(ParameterConstant.COLUMNS, "enable");
                        List<PaasProcessTemplateEntityExt>  processList = paasProcessTemplateModel.list(params);
                        if (!processList.isEmpty() && Objects.equals(processList.get(0).getEnable(), 1)) {
                            buttonPojo.setDisabled(1);
                            buttonPojo.setNeedRemind(1);
                            buttonPojo.setRemindMsg(I18nMessageUtil.getMessage(ErrorMessageConstant.PAY_SHEET_APPROVEL_NOT_ADD));
                        }
                    }

                }
                if (Objects.equals(batchEnum.getAnEnum().getAttr(), SaasBatchEnum.SEND_SMS.getAttr())) {
                    PaasAppEntity entity = paasAppModel.getByAlias(XbbRefTypeEnum.GROUP_MESSAGE.getAlias(), corpid);
                    if (entity == null || Objects.equals(entity.getEnable(), BasicConstant.ZERO)) {
                        continue;
                    }
                }
                Long listGroupIdLong = formDataListDTO.getListGroupId();
                if (listGroupIdLong != null) {
                    Integer listGroupId = listGroupIdLong.intValue();
                    boolean ifMergeInvoicePayment = Objects.equals(XbbRefTypeEnum.PAYMENT_SHEET.getCode(), subBusinessType) &&
                            Objects.equals(batchEnum.getAnEnum().getAttr(), SaasBatchEnum.MERGE_INVOICE.getAttr()) &&
                            (Objects.equals(ListGroupEnum.PAYMENT_SHEET_RED.getCode(), listGroupId) || Objects.equals(ListGroupEnum.PAYMENT_SHEET_BAD.getCode(), listGroupId));
                    boolean ifMergeInvoicePay = Objects.equals(XbbRefTypeEnum.PAY_SHEET.getCode(), subBusinessType) &&
                            Objects.equals(batchEnum.getAnEnum().getAttr(), SaasBatchEnum.MEEGE_PURCHASE_INVOICE.getAttr()) &&
                            (Objects.equals(ListGroupEnum.PAY_SHEET_RED.getCode(), listGroupId) || Objects.equals(ListGroupEnum.PAY_SHEET_BAD.getCode(), listGroupId));
                    if (ifMergeInvoicePayment || ifMergeInvoicePay) {
                        continue;
                    }
                }

                if (Objects.equals(batchEnum.getAnEnum().getAttr(), SaasBatchEnum.CONTRACT_COMPARE.getAttr())) {
                    Boolean showCompareButton = contractCompareUtil.showCompareButton(corpid, permSet, formDataListDTO.getUserId());
                    if (!showCompareButton){
                        continue;
                    }
                }
                buttonPojo.setDistributorMark(distributorMark);
                batchButtonList.add(buttonPojo);
            }

            //打标签
            formDataListAnalysisDataHelp.dealLabelBatch(formDataListDTO, batchButtonList);
            //云叩列表按钮
            setCloudCodeListButton(corpid, formDataListDTO.getLoginUser().getDynamicPermSet(), formDataListDTO.getAppId(), formDataListDTO.getFormId(), businessType, batchButtonList);
            batchButtonList.addAll(getLowCodeButtonList(formDataListDTO));


            return batchButtonList;
        } catch (Exception e) {
            LOGGER.error("AbstractBusinessListService.bottomButton error", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    /**
     * 团队列表权限获取
     * @param formDataListDTO
     * @param explainList
     * @return
     * @throws XbbException
     */
    public Map<String, Boolean> getTeamListPermissionMap(FormDataListDTO formDataListDTO, List<FieldAttrEntity> explainList) throws XbbException {
        return new HashMap<>(BasicConstant.ZERO);
    }

    /**
     * 云叩列表按钮
     * 暂时放这里，后面再改位置
     * @param corpid
     * @param dynamicPermSet
     * @param appId
     * @param formId
     * @param businessType
     * @param buttonPojos
     */
    protected void setCloudCodeListButton(String corpid, Set<String> dynamicPermSet, Long appId, Long formId, Integer businessType, List<ButtonPojo> buttonPojos) {
        if (Objects.isNull(dynamicPermSet)) {
            return;
        }

        if (Objects.nonNull(businessType) && businessType > 0) {
            appId = null;
            formId = null;
        }
        List<CloudCodeControlEntity> cloudCodeControls = cloudCodeControlModel.getByType(corpid, PlatFormEnum.WEB,
                appId, formId, businessType, CloudCodeControlEnum.BUTTON_LIST.getCode());
        if (cloudCodeControls.isEmpty()) {
            return;
        }
        for (CloudCodeControlEntity cloudCodeControl : cloudCodeControls) {
            String alias = PaasConstant.CLOUD_CODE_ALIAS + "_" + cloudCodeControl.getId();
            if (dynamicPermSet.contains(alias)) {
                ButtonPojo buttonPojo = new ButtonPojo();
                buttonPojo.setIcon("icon-18");
                buttonPojo.setAttr(alias);
                buttonPojo.setValue(cloudCodeControl.getName());
                buttonPojo.setActions(cloudCodeControl.getActions());
                buttonPojos.add(buttonPojo);
            }
        }
    }


    protected List<ButtonPojo> getLowCodeButtonList(FormDataListDTO formDataListDTO) throws XbbException {
        return new ArrayList<>();
    }





    /**
     * 获取表单解释，并进行通用处理
     * @param fieldListPojo
     * @param fieldList
     * @return
     * @throws XbbException
     */
    protected List<FieldAttrEntity> commonGetExplain(FieldListPojo fieldListPojo, List<String> fieldList) throws XbbException {
        String corpid = fieldListPojo.getCorpid();
        Long formId = fieldListPojo.getFormId();
        boolean isApprovalGroup = Objects.equals(fieldListPojo.getDefaultGroup(), 1) && Objects.equals(fieldListPojo.getListGroupId(), Long.valueOf(ListGroupEnum.APPROVAL.getCode()));
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
        if (paasFormExplainEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);

        explainList.forEach(item -> {
            // 【审批中】分组数据禁用快速编辑
            if (isApprovalGroup) {
                item.setEditable(0);
            }
            if (!Objects.equals(FieldTypeEnum.SUB_FORM.getType(), item.getFieldType())) {
                fieldList.add(item.getAttr());
            }
            handleFieldAttrEntity(item, fieldListPojo);
        });
        return explainList;
    }

    /**
     * 处理单个FieldAttrEntity
     * @param item
     * @param fieldListPojo
     */
    protected void handleFieldAttrEntity(FieldAttrEntity item, FieldListPojo fieldListPojo) {
        Integer saasMark = fieldListPojo.getSaasMark();
        // saas解释处理
        if (Objects.equals(SaasMarkEnum.SAAS.getCode(), saasMark)) {
            if (Objects.equals(item.getFieldType(), FieldTypeEnum.LINK_BUSINESS_SINGLE.getType())
                    || Objects.equals(item.getFieldType(), FieldTypeEnum.LINK_BUSINESS_MULTI.getType())) {
                LinkDetailPojo linkDetail = new LinkDetailPojo();
                linkDetail.setBusinessType(item.getLinkedType());
                linkDetail.setSubBuisenssType(item.getLinkedType());
                linkDetail.setSaasMark(SaasMarkEnum.SAAS.getCode());
                item.setLinkDetail(linkDetail);
            }
        }
    }

    /**
     * 列表页是否有新建权限
     * 重构前 -> com.xbongbong.saas.service.impl.SaasListServiceImpl#getAppListAddPermission(java.lang.Object)
     * @param formDataListDTO
     * @return
     */
    public boolean isHaveAddPermission (FormDataListDTO formDataListDTO) {
        boolean add = false;
        UserVO userVO = formDataListDTO.getLoginUser();
        List<ListTopButtonEnum> topButtonEnumList = ListTopButtonEnum.getByBusinessType(formDataListDTO.getSubBusinessType());
        for (ListTopButtonEnum topButtonEnum : topButtonEnumList) {
            String permission = topButtonEnum.getProPermissionAlias();
            if (ProPermissionHelp.hasThisPermission(userVO, permission) && Objects.equals(topButtonEnum.getAnEnum(), SaasButtonEnum.ADD)) {
                add = true;
                break;
            }
        }
        return add;
    }

    /**
     * 获取表单
     * @param formDataListDTO
     * @return
     * @throws XbbException
     */
    public PaasFormEntityExt getForm(FormDataListDTO formDataListDTO) throws XbbException{
        Long formId = formDataListDTO.getFormId();
        String corpid = formDataListDTO.getCorpid();
        Integer businessType = formDataListDTO.getBusinessType();
        PaasFormEntityExt form = new PaasFormEntityExt();
        if (formId == null) {
            SheetTypeEnum sheetTypeEnum = SheetTypeEnum.getByBusinessType(businessType);
            boolean sheetFlag = SheetTypeEnum.validateSheet(sheetTypeEnum);
            if (sheetFlag) {
                form = paasFormModel.getByBusinessType4Distributor(sheetTypeEnum.getXbbRefTypeEnum().getCode(), corpid, formDataListDTO.getDistributorMark(), null);
            } else {
                form = paasFormModel.getByBusinessType4Distributor(businessType, corpid, formDataListDTO.getDistributorMark(), null);
            }
            if (form == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
            }
        } else {
            if (Objects.equals(businessType, XbbRefTypeEnum.WORK_ORDER.getCode())) {
                WorkOrderFormEntityExt workOrderForm = workOrderFormModel.getByKey(formId,corpid);
                if (workOrderForm == null) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
                }
                BeanUtil.copyProperties(workOrderForm, form);
            } else {
                form = paasFormModel.getByKey(formId, corpid);
            }
        }
        if (form == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
        }
        paasFormModel.validateByPermission(form, formDataListDTO.getLoginUser());
        formDataListDTO.setDistributorMark(form.getDistributorMark());
        return form;
    }
}
